/*
 * MainFrame.java
 *
 * Created on 2012-04-23, 16:18:14
 */
package gui;

import java.awt.AWTException;
import java.awt.Frame;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.*;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import notifiers.MailSender;
import notifiers.SmsSender;
import parsers.HtmlParser;
import parsers.RSSParser;
import rsshunter.*;

/**
 * Class representing the main frame of RSSHunter.
 */
public class MainFrame extends javax.swing.JFrame {

    /**
     * Creates new form MainFrame
     */
    public MainFrame() {
        //Init GUI components
        initComponents();
        initMyComponents();
        initTray();

        // Initialize variables
        rssBaseFrame = new RssBaseFrame(this);
        htmlBaseFrame = new HtmlBaseFrame(this);
        mailSender = new MailSender("smtp.gmail.com", "587");
        smsSender = new SmsSender();
        rssParser = new RSSParser(this, mailSender, smsSender);
        htmlParser = new HtmlParser(this, mailSender, smsSender);

        //Init models
        initBasesListModel();
        initBasesList();
        initEntriesList();

        //Set program logic components
        UserData ud = db.getUserData();
        if (ud != null) {
            String gmailLogin = ud.getGmailLogin();
            String gmailPass = ud.getGmailPassword();
            mailSender.setTo(ud.getMail());
            mailSender.setAuthentication(gmailLogin, gmailPass);
            smsSender.setAuthentication(gmailLogin, gmailPass);
        }
        scheduler = new Scheduler(basesModel.getBasesList());
        initScheduler();

        //Center frame
        setLocationRelativeTo(null);
        userFrame = new UserFrame(this, mailSender);
    }

    /*
     * Set actual status at status label.
     */
    public synchronized void setStatus(String status) {
        jLabel3.setText(status);
    }

    /*
     * Show popup message at tray.
     */
    public void displayTrayMessage(String title, String message) {
        if (!isFocused() || getState() == Frame.ICONIFIED) {
            trayIcon.displayMessage(title, message, TrayIcon.MessageType.NONE);
        }
    }

    /**
     * Enable/Dispable check button.
     */
    public void enableCheckButton(boolean b) {
        jButton3.setEnabled(b);
    }

    /**
     * Refresh entries pane.
     */
    public void refresh() {
        showEntries(actualBase);
        repaint();
    }

    public BasesListModel getBasesModel() {
        return basesModel;
    }

    public Scheduler getScheduler() {
        return scheduler;
    }

    public JProgressBar getProgressBar() {
        return jProgressBar1;
    }

    private void initMyComponents() {
        basesPopup = new JPopupMenu();
        JMenuItem renameItem = new JMenuItem("Rename");
        renameItem.addActionListener(new ChangeNameAction());

        JMenuItem propertiesItem = new JMenuItem("Properties");
        propertiesItem.addActionListener(new BasePreferencesListener());

        JMenuItem removeItem = new JMenuItem("Remove");
        removeItem.addActionListener(new DeleteBaseAction());

        basesPopup.add(renameItem);
        basesPopup.add(propertiesItem);
        basesPopup.add(removeItem);
        
        jTextPane1.addHyperlinkListener(new UriClickedListener());
    }

    private void initBasesList() {
        jList1.setModel(basesModel);
        ListSelectionModel sModel = jList1.getSelectionModel();
        sModel.addListSelectionListener(new BaseSelectionHandler());
        jList1.addMouseListener(new BasesMouseListener());

        // Map delete key
        jList1.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
                "deleteElement");
        jList1.getActionMap().put("deleteElement", new DeleteBaseAction());
    }

    private void initBasesListModel() {
        basesModel = new BasesListModel();
        LinkedList<RSSBase> basesList = db.getBases();
        for (RSSBase base : basesList) {
            switch (base.getType()) {
                case RSSBase.RSS:
                    base.setParser(rssParser);
                    break;
                case RSSBase.HTML:
                    base.setParser(htmlParser);
                    break;
            }
            basesModel.addBase(base);
        }
    }

    private void initEntriesList() {
        entriesModel = (EntriesTableModel) jTable2.getModel();
        ListSelectionModel sModel = jTable2.getSelectionModel();
        sModel.addListSelectionListener(new EntrySelectionHandler());

        // Map delete key
        jTable2.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
                "deleteElement");
        jTable2.getActionMap().put("deleteElement", new DeleteEntryAction());
    }

    private void initScheduler() {
        scheduler.init();
    }

    private void initTray() {
        if (!SystemTray.isSupported()) {
            System.err.println("SystemTray is not supported");
            return;
        }
        final SystemTray tray = SystemTray.getSystemTray();
        trayIcon = new RSSHunterTray(this);
        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.err.println("TrayIcon could not be added:" + e);
        }
    }

    private void showEntries(String baseName) {
        entriesModel.setData(db.getEntries(new RSSBase(baseName)));
        entriesModel.fireTableDataChanged();
    }

    private void showEntry(RSSEntry entry) {
        String toDisplay = entry.getDescription()
                + "<br/><br/><a href=\"" + entry.getUri() + "\">"
                + "Show in browser</a>";
        HTMLEditorKit kit = new HTMLEditorKit();
        HTMLDocument doc = new HTMLDocument();
        jTextPane1.setEditorKit(kit);
        jTextPane1.setDocument(doc);
        try {
            kit.insertHTML(doc, doc.getLength(),
                    toDisplay, 0, 0, null);
        } catch (BadLocationException e) {
            System.err.println(
                    "Bad location when displaying entry: " + e);
        } catch (IOException e) {
            System.err.println("Error displaying entry: " + e);
        }
    }
    
    /**
     * Tries to open url in default system browser.
     * @param Url to open.
     */
    private void openInBrowser(String url) {
        if (!java.awt.Desktop.isDesktopSupported()) {
            setStatus("Desktop is not supported.");
            return;
        }
        java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
        if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
            setStatus("Desktop doesn't support the browse action.");
            return;
        }

        try {
            java.net.URI uri = new java.net.URI(url);
            desktop.browse(uri);
        } catch (Exception e) {
            System.err.println("Error displaying hyperlink in brwser: " + e);
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane4 = new javax.swing.JScrollPane();
        jTable2 = new javax.swing.JTable();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextPane1 = new javax.swing.JTextPane();
        jLabel3 = new javax.swing.JLabel();
        jProgressBar1 = new javax.swing.JProgressBar();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(14, 0), new java.awt.Dimension(14, 0), new java.awt.Dimension(14, 32767));
        jLabel4 = new javax.swing.JLabel();

        setTitle("RssHunter");
        setIconImage(new ImageIcon("Icons/rssicon.png").getImage());

        jScrollPane1.setViewportView(jList1);

        jButton1.setFont(new java.awt.Font("Dialog", 1, 10)); // NOI18N
        jButton1.setText("New base");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jButton2.setFont(new java.awt.Font("Dialog", 1, 10)); // NOI18N
        jButton2.setText("Base properties");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showBaseProperties(evt);
            }
        });

        jButton3.setFont(new java.awt.Font("Dialog", 1, 10)); // NOI18N
        jButton3.setText("Check");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jButton4.setFont(new java.awt.Font("Dialog", 1, 10)); // NOI18N
        jButton4.setText("User properties");
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton4ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton4)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButton3)
                    .addComponent(jButton4))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jLabel1.setFont(new java.awt.Font("Dialog", 1, 11)); // NOI18N
        jLabel1.setText("Bases:");

        jLabel2.setFont(new java.awt.Font("Dialog", 1, 11)); // NOI18N
        jLabel2.setText("Items:");

        jTable2.setModel(new EntriesTableModel());
        jScrollPane4.setViewportView(jTable2);

        jTextPane1.setContentType("text/html");
        jTextPane1.setEditable(false);
        jTextPane1.setFocusable(false);
        jScrollPane2.setViewportView(jTextPane1);

        jLabel3.setFont(new java.awt.Font("Tahoma", 0, 10)); // NOI18N
        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText(" Program ready");

        jProgressBar1.setMaximumSize(new java.awt.Dimension(32767, 13));
        jProgressBar1.setMinimumSize(new java.awt.Dimension(10, 13));
        jProgressBar1.setPreferredSize(new java.awt.Dimension(146, 13));

        jLabel4.setFont(new java.awt.Font("Dialog", 1, 11)); // NOI18N
        jLabel4.setText("Preview:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel1)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jScrollPane4)
                            .addComponent(jScrollPane2)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel2)
                                    .addComponent(jLabel4))
                                .addGap(0, 0, Short.MAX_VALUE))))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(filler1, javax.swing.GroupLayout.DEFAULT_SIZE, 112, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 403, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(jLabel2))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel4)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(filler1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );

        jLabel3.getAccessibleContext().setAccessibleName("statusLabel");

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
    // Show new base dialog
    if (newBaseDialog == null) {
        newBaseDialog = new NewBaseDialog(this, true);
        newBaseDialog.setVisible(true);
    } else {
        newBaseDialog.resetFields();
        newBaseDialog.setVisible(true);
    }

    if (newBaseDialog.getReturnStatus() == NewBaseDialog.RET_CANCEL) {
        // Do nothing if user canceled
        return;
    }

    //Get base parameters from dialog
    String name = newBaseDialog.getBaseName();
    byte type = newBaseDialog.getBaseType();

    if (name == null || name.equals("")) {
        setStatus("Base name cannot be empty.");
        return;
    }

    // Save this base in model and database
    RSSBase base = new RSSBase(name);
    base.setType(type);
    if (db.addBase(base)) {

        //Set proper parser
        switch (type) {
            case RSSBase.RSS:
                base.setParser(rssParser);
                break;
            case RSSBase.HTML:
                base.setParser(htmlParser);
                break;
        }
        basesModel.addBase(base);
        scheduler.updateAllBases();
        setStatus("Base " + name + " successfully added.");
    } else {
        setStatus("Base " + name + " already exists.");
    }
}//GEN-LAST:event_jButton1ActionPerformed

private void showBaseProperties(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showBaseProperties
    actualBase = (String) jList1.getSelectedValue();
    int actualIndex = jList1.getSelectedIndex();
    if (actualIndex < 0) {
        setStatus("No database selected.");
        return;
    }
    RSSBase base = basesModel.getBase(actualIndex);

    if (actualBase != null) {
        switch (base.getType()) {
            case RSSBase.RSS:
                rssBaseFrame.show(actualBase);
                break;
            case RSSBase.HTML:
                htmlBaseFrame.show(actualBase);
                break;
        }
        setStatus("Base " + actualBase + " properties changed.");
    }
}//GEN-LAST:event_showBaseProperties

    private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
        userFrame.setVisible(true);
        setStatus("User properties changed.");
    }//GEN-LAST:event_jButton4ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        int index = jList1.getSelectedIndex();
        if (index >= 0) {
            RSSBase base = basesModel.getBase(index);
            setStatus("Checking base " + base.getName() + "...");
            base.check();
        } else {
            setStatus("No database selected.");
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    private class BaseSelectionHandler implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            boolean isAdjusting = e.getValueIsAdjusting();
            if (isAdjusting == false) {
                String baseName = (String) jList1.getSelectedValue();
                if (baseName != null && !baseName.equals(actualBase)) {
                    showEntries(baseName);
                    actualBase = baseName;
                    jTable2.clearSelection();
                    jTextPane1.setText("");
                }
            }
        }
    }

    private class EntrySelectionHandler implements ListSelectionListener {

        @Override
        public void valueChanged(ListSelectionEvent e) {
            boolean isAdjusting = e.getValueIsAdjusting();
            if (isAdjusting == false) {
                int row = jTable2.getSelectedRow();
                if (row >= 0) {
                    showEntry(entriesModel.getEntry(row));
                }
            }
        }
    }
    
    private class UriClickedListener implements HyperlinkListener {

        @Override
        public void hyperlinkUpdate(HyperlinkEvent hyperlinkEvent) {
            HyperlinkEvent.EventType type = hyperlinkEvent.getEventType();
            if (type == HyperlinkEvent.EventType.ACTIVATED) {
                openInBrowser(hyperlinkEvent.getURL().toString());
            }
        }
        
    }

    private class BasePreferencesListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            showBaseProperties(e);
        }
    }

    private class DeleteBaseAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (actualBase == null) {
                setStatus("No database selected.");
                return;
            }

            RSSBase base = basesModel.getBase(actualBase);
            if (base.getType() == RSSBase.HTML) {
                // Delete base page content files
                List<RSSChannel> channels = db.getChannels(actualBase);
                for (RSSChannel channel : channels) {
                    HtmlParser.deletePageContentFile(channel);
                }
            } else if (base.getType() == RSSBase.RSS) {
                entriesModel.clear();
                jTextPane1.setText("");
            }

            db.deleteBase(actualBase);
            basesModel.removeElementAt(jList1.getSelectedIndex());
            actualBase = null;
        }
    }

    private class ChangeNameAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {
            if (actualBase == null) {
                setStatus("No database selected.");
                return;
            }

            String name = JOptionPane.showInputDialog(rootPane,
                    "Type new base name:",
                    "Rename base",
                    JOptionPane.PLAIN_MESSAGE);
            if (name == null || name.equals("")) {
                setStatus("Base name cannot be empty.");
                return;
            }

            if (db.changeBaseName(actualBase, name)) {
                basesModel.changeBaseName(actualBase, name);
                setStatus("Base " + actualBase + " renamed to " + name + ".");
                actualBase = name;
                jList1.repaint();
            } else {
                setStatus("Base name " + actualBase + " already exists.");
            }
        }
    }

    private class DeleteEntryAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {
            int[] selected = jTable2.getSelectedRows();
            List<RSSEntry> entries = new LinkedList<RSSEntry>();
            for (int index : selected) {
                RSSEntry entry = entriesModel.getEntry(index);
                entries.add(entry);
            }
            db.deleteEntries(entries);
            entriesModel.removeByIndexes(selected);
            jTable2.clearSelection();
            jTable2.revalidate();
            jTextPane1.setText("");
            MainFrame.this.repaint();
        }
    }

    private class BasesMouseListener extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
                showBaseProperties(null);
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
            check(e);
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            check(e);
        }

        public void check(MouseEvent e) {
            if (e.isPopupTrigger()) {
                //  jList1.setSelectedIndex(jList1.locationToIndex(e.getPoint())); //select the item
                basesPopup.show(jList1, e.getX(), e.getY()); //and show the menu
            }
        }
    }
    private NewBaseDialog newBaseDialog;
    private final MailSender mailSender;
    private final SmsSender smsSender;
    private final RSSParser rssParser;
    private final HtmlParser htmlParser;
    private final Scheduler scheduler;
    private final DB db = new DB();
    private BasesListModel basesModel;
    private EntriesTableModel entriesModel;
    private final RssBaseFrame rssBaseFrame;
    private final HtmlBaseFrame htmlBaseFrame;
    private final UserFrame userFrame;
    private String actualBase;
    private JPopupMenu basesPopup;
    private TrayIcon trayIcon;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler1;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JList jList1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JTable jTable2;
    private javax.swing.JTextPane jTextPane1;
    // End of variables declaration//GEN-END:variables
}
